package cn.bonoon.kernel.menus;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.w3c.dom.Element;

import cn.bonoon.kernel.VisibleScope;
import cn.bonoon.kernel.config.ConfigParser;
import cn.bonoon.kernel.util.StringHelper;

/**
 * 
 * @author jackson
 * @version 2012-6-20 添加在样式中对系统名称的图片支持
 * 
 */
public final class ModulesDefinitionParser extends ConfigParser {

	protected Class<?> getBeanClass(Element element) {
		Class<?> cls = getClass(element);
		if (null == cls){
			cls = StandardModuleManager.class;
		}
		return cls;
	}

	protected void doParse(Element element, BeanDefinitionBuilder bean) {
		bean.addPropertyValue("id", getId(element));
		bean.addPropertyValue("name", getName(element));
		bean.addPropertyValue("endpoint", getText(element, "host"));
		bean.addPropertyValue("path", element.getAttribute("path"));

		_parseEmbed(bean, element);
		
		_parseDes(bean, element);

		_parseStyle(bean, element(element, "style"));
			
		_parseLogin(bean, element);
		
		ManagedList<BeanDefinition> voters =  new ManagedList<BeanDefinition>();
		for (Element eleModule : elements(element, "module")) {
			BeanDefinitionBuilder moduleBuilder = BeanDefinitionBuilder.rootBeanDefinition(ModuleInfo.class);
			moduleBuilder.addPropertyValue("id", getId(eleModule));
			moduleBuilder.addPropertyValue("name", getName(eleModule));
			moduleBuilder.addPropertyValue("ordinal", getOrdinal(eleModule));
			moduleBuilder.addPropertyValue("thumbnail", eleModule.getAttribute("thumbnail"));
			moduleBuilder.addPropertyValue("path", eleModule.getAttribute("path"));

			_parseEmbed(moduleBuilder, eleModule);
			
			_parseDes(moduleBuilder, eleModule);
			
			_parseStyle(moduleBuilder, eleModule);
			
			List<ChannelInfo> channels = new ArrayList<ChannelInfo>();
			for (Element eleChannel : elements(eleModule, "channel")) {
				ChannelInfo channelInfo = new ChannelInfo();
				_parseAttribute(channelInfo, eleChannel);
				channels.add(channelInfo);
				_parseMenu(channelInfo, eleChannel);
				//TODO 读取tabs信息
				_parseTabs(channelInfo, eleChannel);
			}
			moduleBuilder.addConstructorArgValue(channels);
			voters.add(moduleBuilder.getBeanDefinition());
		}
		bean.addConstructorArgValue(voters);
	}
	
	private void _parseLogin(BeanDefinitionBuilder bean, Element element){
		Element eleLogin = element(element, "login");
		if(null != eleLogin){
			bean.addPropertyValue("loginName", getValue(eleLogin, "name"));
			bean.addPropertyValue("loginTitle", getValue(eleLogin, "title"));
			bean.addPropertyValue("loginFoot", getValue(eleLogin, "foot"));
			bean.addPropertyValue("loginLogo", getValue(eleLogin, "logo"));

			bean.addPropertyValue("loginLayout", eleLogin.getAttribute("layout"));
		}
	}
	
	private void _parseEmbed(BeanDefinitionBuilder moduleBuilder, Element eleModule){
		List<PartInfo> parts = new ArrayList<PartInfo>();
		for(Element part : elements(eleModule, "embed")){
			String url = part.getAttribute("url");
			if(StringHelper.isEmpty(url)){ continue; }
			
			String name = getName(part);
			if(StringHelper.isEmpty(name)){ continue; }
			
			PartInfo hpi = new PartInfo(name, url);
			hpi.setOrdinal(getOrdinal(part));
			hpi.setLevel(getInt(part, "level"));
			hpi.setHelper(getBool(part, "helper"));
			hpi.setIconCls(part.getAttribute("iconCls"));
			parts.add(hpi);
		}
		moduleBuilder.addPropertyValue("parts", parts);
	}
	
	private void _parseDes(BeanDefinitionBuilder moduleBuilder, Element eleModule){
		Element eleDes = element(eleModule, "des");
		if(null != eleDes){
			moduleBuilder.addPropertyValue("des", new DesInfo(eleDes.getTextContent(), eleDes.getAttribute("type"), getInt(eleDes, "height")));
		}
	}

	private void _parseTabs(ChannelInfo channel, Element element) {
		for (Element eleTabs : elements(element, "tabs")) {
			TabInfo tabs = new TabInfo();
			tabs.setId(getId(eleTabs));
			tabs.setName(getName(eleTabs));
			tabs.setOrdinal(getOrdinal(eleTabs));
			tabs.setTitle(getValue(eleTabs, "title"));
			for (Element eleTab : elements(eleTabs, "tab")) {
				ITabParser parser = null;
				Class<?> cls = getClass(eleTab);
				if(null != cls){
					parser = new ClassTabParser(cls, eleTab.getAttribute("scope"));
				}else{
					String href = getValue(eleTab, "href");
					if(StringHelper.isEmpty(href)){
						continue;
					}
					parser = new SimpleTabParser(href, eleTab.getAttribute("type"));
				}
				TabItem tab = new TabItem(tabs, parser);
				tab.setId(getId(eleTab));
				tab.setName(getName(eleTab));
				tab.setOrdinal(getOrdinal(eleTab));
				tabs.add(tab);
			}
			channel.add(tabs);
		}
	}

	private void _parseMenu(ItemInfo item, Element element) {
		for (Element eleMenu : elements(element, "menu")) {
			MenuInfo menu = new MenuInfo();
			_parseAttribute(menu, eleMenu);
			menu.setIconCls(eleMenu.getAttribute("iconCls"));
			item.add(menu);
			_parseMenu(menu, eleMenu);
		}
	}

	private void _parseStyle(BeanDefinitionBuilder bean, Element style) {
		bean.addPropertyValue("systemTitle", getValue(style, "title"));
		bean.addPropertyValue("systemLogo", getValue(style, "logo"));
		bean.addPropertyValue("footName", getValue(style, "foot"));
		bean.addPropertyValue("footHeight", getInt(style, "foot-height"));
		bean.addPropertyValue("menuWidth", getInt(style, "menu-width"));
		bean.addPropertyValue("topHeight", getInt(style, "top-height"));
		bean.addPropertyValue("systemName", getValue(style, "image"));
	}
	
	private VisibleScope __scope(Element element){
		String scope = element.getAttribute("scope");
		if(StringHelper.isNotEmpty(scope)){
			try{
				return VisibleScope.valueOf(scope);
			}catch(Exception ex){}
		}
		return VisibleScope.DOMAIN;
	}

	private void _parseAttribute(ItemInfo item, Element element) {
		item.setId(getId(element));
		item.setName(getName(element));
		item.setOrdinal(getOrdinal(element));
		item.setTitle(getValue(element, "title"));
		item.setAttrs(getValue(element, "attrs"));
		item.setArgs(getValue(element, "args"));
		item.setTarget(getValue(element, "target"));
		item.setHref(getValue(element, "href"));
		item.setScope(__scope(element));

		Element eleDes = element(element, "des");
		if(null != eleDes){
			item.setDes(new DesInfo(
					eleDes.getTextContent(), 
					eleDes.getAttribute("type"), 
					getInt(eleDes, "height")));
		}

		List<ActionInfo> actions = new ArrayList<ActionInfo>();
		int actionPrivileges = 0;
		for (Element eleAction : elements(element, "action")) {
			int key = getInt(eleAction, "key");
			actions.add(new ActionInfo(key, getName(eleAction)));
			actionPrivileges = actionPrivileges | (1 << key);
		}
		int size = actions.size();
		if(size > 0){
			item.setActions(actions.toArray(new ActionInfo[size]));
		}
		item.setActionPrivileges(actionPrivileges);
	}
}
